#include "Arp.h"
#include <EEPROM.h>

#include "HardwareSerial.h"
#include <MIDI.h>

Arp::Arp(MIDI * midi) {
	steps = 0;
	length = 1;
        syncc = 0;
        notec = 0;
        this->midi = midi;
        currentStep = 0;
        currentNote = -1;
        playing = false;
}

int Arp::getSteps() {
	return steps;
}

int Arp::getLength() {
	return length;
}

int Arp::getTune(int step) {
	return tune[step];
}

void Arp::readFromSerial() {
  if (Serial.available() > 0) {
    steps = Serial.read();
    delayMicroseconds(4250);
    for (int i = 0; i < steps; i++) {
      tune[i] = Serial.read();
      delayMicroseconds(4250);      
    }
    length = Serial.read();
    delayMicroseconds(4250);
  }
}

void Arp::writeToSerial() {
	Serial.write(steps);
	for (int i = 0; i < steps; i++) {
		Serial.write(tune[i]);
	}
	Serial.write(length);
}

void Arp::readFromMemory(int index) {
	steps = EEPROM.read(index);
        if (steps == 1) {
         // digitalWrite(13, HIGH);
         // delay(1000);
         // digitalWrite(13, LOW);
         // delay(1000);
        }
	for (int i = 0; i < steps; i++) {
          tune[i] = EEPROM.read(i + 1 + index);
	}
	length = EEPROM.read(steps + 1 + index);
        /*if (length == 16) {
          digitalWrite(13, HIGH);
          delay(1000);
          digitalWrite(13, LOW);
          delay(1000);
        }*/
}

void Arp::writeToMemory(int index) {
	EEPROM.write(index, steps);
	for (int i = 0; i < steps; i++) {
		EEPROM.write(i + 1 + index, tune[i]);
                //digitalWrite(13, HIGH);
                delay(1000);
                digitalWrite(13, LOW);
                delay(1000);
	}
	EEPROM.write(steps + 1 + index, length);
}

void Arp::handleStart() {
  syncc = 0;
  midi->send(midi->getStatus());
}

void Arp::handleNoteOn() {
  if (notec < 3) {
    if (playing) { // Send note off for currently playing
      midi->send(notes[currentNote][0] - 0x10, notes[currentNote][1], notes[currentNote][2]);
    }    
    midi->send(midi->getStatus(), midi->getData1(), midi->getData2());
    notes[notec][0] = midi->getStatus();
    notes[notec][1] = midi->getData1();
    notes[notec][2] = midi->getData2();
    currentNote = notec; // ??
    notec++;
    playing = true; // read + cmp > write
    
    //if (midi->getStatus() < 144) {
    //if (notes[notec - 1][0] == 0x90) {
      //digitalWrite(13, HIGH);
      //delay(1000);
      //digitalWrite(13, LOW);
    //}
  } 
}

void Arp::handleNoteOff() {
  if (notes[currentNote][1] == midi->getData1()) {
    midi->send(midi->getStatus(), midi->getData1(), midi->getData2()); // if currently playing this note!!!
    playing = false;
    currentNote--;
  }  
  
  if (notec > 1) {   
    /*int i = 0;
    boolean nfound = true;
    while ((nfound) && (i < notec)) {
      digitalWrite(13, HIGH);
      delay(1000);
      digitalWrite(13, LOW); 
      if (notes[i][1] == midi->getData1()) {
        nfound = false;
      }
      else {
        i++;
      }
    }*/
    /*digitalWrite(13, HIGH);
    delay(1000);
    digitalWrite(13, LOW);*/
    int i = 0;
    boolean found = false;
    for (int x = 0; x < notec; x++) {
      if (notes[x][1] == midi->getData1()) {
        i = x;
        found = true;
        break;
      }
    }
    
    if (found) {
      if (notec > 1) { // more than one note
        if (i < notec - 1) { // not the last one
          for (int x = i; x < notec; x++) { // copy one row down
            notes[x][0] = notes[x + 1][0];
            notes[x][1] = notes[x + 1][1];
            notes[x][2] = notes[x + 1][2];
          }
        }
      }
    }  
  }
  // finish step with prev note ???
  else if (notec > 0) {
    // do nothing
  }
  notec--;  // done or one note (or 0 but shouldn't happen)
}

void Arp::sync() {
  midi->send(midi->getStatus());
  syncc++; // This needs some work
  if (syncc == (24 / (length / 4))) { // Begin of new step
    syncc = 0;
    if (notec > 0) {
      if (playing) {      
        midi->send(notes[currentNote][0] - 0x10, notes[currentNote][1] + tune[currentStep], notes[currentNote][2]); // Send noteoff for currently playing note
      }
      if (currentStep < steps - 1) {
        currentStep++;
      }
      else {
        currentStep = 0;
      }
      if (currentNote < notec - 1) {
        currentNote++;
      }
      else {
        currentNote = 0;
      }
      midi->send(notes[currentNote][0], notes[currentNote][1] + tune[currentStep], notes[currentNote][2]);
      playing = true;
    }
  }
  /*if (syncc > 24) {
    syncc = 0;
  }*/
}
